package com.kujawnode.config.filter;

import com.kujawnode.constant.Constants;
import com.kujawnode.model.TUser;
import com.kujawnode.result.CodeEnum;
import com.kujawnode.result.R;
import com.kujawnode.service.RedisService;
import com.kujawnode.utils.JSONUtils;
import com.kujawnode.utils.JWTUtils;
import com.kujawnode.utils.ResponseUtils;
import io.netty.util.internal.StringUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @version 1.0
 * @Author kujaw
 * @Date 2025/7/11 12:53
 * @注释
 */
@Component
public class TokenVerifyFilter extends OncePerRequestFilter {

    @Resource
    private RedisService redisService;

    //spring boot框架ioc容器中已经创建好了改线程池，可以注入直接使用
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //如果是登录请求，此时没有jwt，不需要对登录请求进行token检验
        if(request.getRequestURI().equals(Constants.LOGIN_URI)){
            //验证token通过了，让Filter链继续执行，也就是继续执行下一个Filter
            filterChain.doFilter(request,response);
        }else{
            String token = request.getHeader("Authorization");
            if(!StringUtils.hasText(token)){
                //token验证未通过的统一结果
                R result = R.FAIL(CodeEnum.TOKEN_IS_EMPTY);

                //把R对象转成json
                String resultJSON = JSONUtils.toJSON(result);

                //把R以JSON形式返回给前端
                ResponseUtils.write(response,resultJSON);
                return;
            }

            //验证token是否被篡改
            if(!JWTUtils.verifyJWT(token)){
                //token验证未通过的统一结果
                R result = R.FAIL(CodeEnum.TOKEN_IS_ABNORMAL);

                //把R对象转成json
                String resultJSON = JSONUtils.toJSON(result);

                //把R以JSON形式返回给前端
                ResponseUtils.write(response,resultJSON);
                return;
            }

            TUser tUser = JWTUtils.parseUserFromJWT(token);
            String redisToken = (String) redisService.getValue(Constants.REDIS_JWT_KEY + tUser.getId());

            if(!StringUtils.hasText(redisToken)){
                //token验证未通过的统一结果
                R result = R.FAIL(CodeEnum.TOKEN_IS_EXPIRE);

                //把R对象转成json
                String resultJSON = JSONUtils.toJSON(result);

                //把R以JSON形式返回给前端
                ResponseUtils.write(response,resultJSON);
                return;
            }

            if(!redisToken.equals(token)){
                //token验证未通过的统一结果
                R result = R.FAIL(CodeEnum.TOKEN_IS_ERROR);

                //把R对象转成json
                String resultJSON = JSONUtils.toJSON(result);

                //把R以JSON形式返回给前端
                ResponseUtils.write(response,resultJSON);
                return;
            }

            //token验证通过，在spring security的上下文环境设置一下，设置当前个人是登录过来的，不要再进行拦截
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(
                            tUser,
                            tUser.getLoginPwd(),
                            tUser.getAuthorities()
                    );
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);

            //刷新token时间(异步处理)
            //  new Thread(()->{
            //      String rememberMe = request.getHeader("rememberMe");
            //      if(Boolean.parseBoolean(rememberMe)){
            //          redisService.setExpire(
            //                  Constants.REDIS_JWT_KEY+tUser.getId(),
            //                  Constants.EXPIRE_TIME,
            //                  TimeUnit.SECONDS
            //          );
            //      }else{
            //          redisService.setExpire(
            //                  Constants.REDIS_JWT_KEY+tUser.getId(),
            //                  Constants.DEFAULT,
            //                  TimeUnit.SECONDS
            //          );
            //      }
            //  }).start();

             //更好的方式，线程池
            threadPoolTaskExecutor.execute(()->{
                String rememberMe = request.getHeader("rememberMe");
                if(Boolean.parseBoolean(rememberMe)){
                    redisService.setExpire(
                            Constants.REDIS_JWT_KEY+tUser.getId(),
                            Constants.EXPIRE_TIME,
                            TimeUnit.SECONDS
                    );
                }else{
                    redisService.setExpire(
                            Constants.REDIS_JWT_KEY+tUser.getId(),
                            Constants.DEFAULT,
                            TimeUnit.SECONDS
                    );
                }
            });

            //验证token通过，让Filter链继续执行
            filterChain.doFilter(request,response);
        }
    }
}
